/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.action.query;

import com.inspur.edp.bef.api.action.assembler.IMgrActionAssembler;
import com.inspur.edp.bef.api.be.IBEManagerContext;
import com.inspur.edp.bef.api.exceptions.BefException;
import com.inspur.edp.bef.api.exceptions.BefFuncPermissionDeniedException;
import com.inspur.edp.bef.api.exceptions.ErrorCodes;
import com.inspur.edp.bef.core.action.AuthorityUtil;
import com.inspur.edp.bef.core.be.BEManager;
import com.inspur.edp.bef.core.be.BEManagerContext;
import com.inspur.edp.bef.core.be.BusinessEntity;
import com.inspur.edp.bef.core.determination.BeforeQueryDtmExecutor;
import com.inspur.edp.bef.entity.exception.ExceptionLevel;
import com.inspur.edp.bef.spi.action.AbstractManagerAction;
import com.inspur.edp.bef.spi.action.assembler.query.QueryMgrActionAssembler;
import com.inspur.edp.bef.spi.event.queryactionevent.BefQueryEventBroker;
import com.inspur.edp.cef.api.authority.AuthorityInfo;
import com.inspur.edp.cef.api.repository.IRootRepository;
import com.inspur.edp.cef.entity.condition.EntityFilter;
import com.inspur.edp.cef.entity.condition.ExpressCompareType;
import com.inspur.edp.cef.entity.condition.FilterCondition;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.spi.determination.IEntityRTDtmAssembler;
import io.iec.edp.caf.permission.api.data.runtime.datapermission.DataPermissionQueryFilter;
import io.iec.edp.caf.permission.api.manager.runtime.DataPermissionManager;
import io.iec.edp.caf.runtime.config.CefBeanUtil;
import io.iec.edp.caf.securityentry.api.common.AuthType;
import io.iec.edp.caf.securityentry.api.data.AuthFieldEntry;
import io.iec.edp.caf.securityentry.api.data.DataPermissionEntity;
import io.iec.edp.caf.securityentry.api.data.PermissionEntity;
import io.iec.edp.caf.securityentry.api.data.SecurityEntry;
import io.iec.edp.caf.securityentry.api.manager.SecurityEntryService;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.util.StringUtils;

public class QueryManagerAction extends AbstractManagerAction<List<IEntityData>> {
    protected String nodeCode;
    protected EntityFilter filter;
    private EntityFilter privateFinalFilter;

    protected final EntityFilter getFinalFilter() {
        return privateFinalFilter;
    }

    private void setFinalFilter(EntityFilter value) {
        privateFinalFilter = value;
    }

    // TODO:wj-Query考虑权限问题
    public QueryManagerAction(
            IBEManagerContext managerContext, String nodeCode, EntityFilter filter) {
        super(managerContext);
        this.nodeCode = nodeCode;
        this.filter = filter;
    }

    @Override
    public void execute() {
//        AuthorityUtil.checkAuthority("Query");

        EntityFilter customEntityFilter = getCustomEntityFilter();
        setFinalFilter(mergeEntityFilter(filter, customEntityFilter));

        // 查询前联动计算自定义过滤条件
        try {
            BefQueryEventBroker.fireBeforeTotalCXQDeterminate(filter, customEntityFilter, getFinalFilter());
            // 查询前联动计算自定义过滤条件
            int count = Determinate();
            BefQueryEventBroker.fireAfterTotalCXQDeterminate(getFinalFilter(), count);
        } catch (Exception e) {
            BefQueryEventBroker.fireQueryUnnormalStop(e);
            throw new RuntimeException(e);
        }

        // 执行查询
        IRootRepository repository = getBEManagerContext().getBEManager().getRepository();
        List<IEntityData> datas;
        try {
            BefQueryEventBroker.firebeforeCoreQuery(getFinalFilter());
            datas = repository.query(nodeCode, getFinalFilter(), getAuthorityInfosWithQuery((BEManagerContext)getBEManagerContext())).stream()
                    .map(item -> (IEntityData) item)
                    .collect(Collectors.toList());
            BefQueryEventBroker.fireafterCoreQuery(getBEManagerContext().getBEManager(), datas);
        } catch (Exception e) {
            BefQueryEventBroker.fireQueryUnnormalStop(e);
            throw new RuntimeException(e);
        }

        // 查询后联动计算修改虚拟字段
        try {
            BefQueryEventBroker.fireBeforeTotalCXHDeterminate(getBEManagerContext().getBEManager(), datas);
            if (datas != null) {
                for (IEntityData data : datas) {
                    try {
                        BusinessEntity entity =
                                (BusinessEntity)
                                        getBEManagerContext().getBEManager().createSessionlessEntity(data.getID());
                        entity.getBEContext().setCurrentData(data);
                        entity.afterQueryDeterminate();
                    } catch (Exception e) {
                        BefQueryEventBroker.fireQueryUnnormalStop(e);
                        throw new RuntimeException(e);
                    }
                }
            }
            BefQueryEventBroker.fireafterTotalCXHDeterminate(getBEManagerContext().getBEManager(), datas, (datas == null ? 0 : datas.size()));
        } catch (Exception e) {
            BefQueryEventBroker.fireQueryUnnormalStop(e);
            throw new RuntimeException(e);
        }
        setResult(datas);
    }

    private  int  Determinate() {
        if(!StringUtils.isEmpty(nodeCode) && getBEManagerContext().getBEManager().getRootEntityResInfo() != null
            && !StringUtils.isEmpty(getBEManagerContext().getBEManager().getRootEntityResInfo().getEntityCode())
            && !nodeCode.equalsIgnoreCase(getBEManagerContext().getBEManager().getRootEntityResInfo().getEntityCode())) {
                return 0;
        }
        IEntityRTDtmAssembler queryDtmAss =
            ((BEManager) getBEManagerContext().getBEManager()).getBeforeQueryDtmAssembler();
        if (queryDtmAss == null) {
            return 0;
        }
        BeforeQueryDtmExecutor dtmExecutor =
                new BeforeQueryDtmExecutor(queryDtmAss, getBEManagerContext());
//        dtmExecutor.setFinalFilter(getFinalFilter());
        int count = dtmExecutor.execute();
        if (dtmExecutor.getFilter() != null) {
            setFinalFilter(mergeEntityFilter(getFinalFilter(), dtmExecutor.getFilter()));
        }
        return count;
    }

    private boolean checkFilter(EntityFilter checkFilter) {
        if (checkFilter == null
                || checkFilter.getFilterConditions() == null
                || checkFilter.getFilterConditions().isEmpty()) {
            return true;
        }
for (FilterCondition condition : checkFilter.getFilterConditions()) {
            if (condition.getValue() != null
                    && condition.getValue().contains("'")
                    && (condition.getCompare() == ExpressCompareType.Like
                    || condition.getCompare() == ExpressCompareType.LikeStartWith
                    || condition.getCompare() == ExpressCompareType.LikeEndWith
                    || condition.getCompare() == ExpressCompareType.NotLike
                    || condition.getCompare() == ExpressCompareType.NotLikeStartWith
                    || condition.getCompare() == ExpressCompareType.NotLikeEndWith)) {
                return false;
            }
        }

        return true;
    }

    protected ArrayList<AuthorityInfo> getAuthorityInfosWithQuery(BEManagerContext beManagerContext){
        return  getAuthorityInfos(beManagerContext);
    }

//    public static java.util.ArrayList<AuthorityInfo> getAuthorityInfos(IBEManagerContext ibeManagerContext) {
//
//        ArrayList<AuthorityInfo> list = new ArrayList<AuthorityInfo>();
//        if (!AuthorityUtil.hasAuthority(ibeManagerContext))
//            return list;
//        SecurityEntryService service = CefBeanUtil.getAppCtx().getBean(SecurityEntryService.class);
//        SecurityEntry entry = AuthorityUtil.createEntry(AuthType.Auth);
//        PermissionEntity permissionEntity= service.getPermission( entry, "Query");
//
//        if(permissionEntity==null)
//            return list;
//        if(permissionEntity.isActionEnable()==false)
//        {
//            throw new BefFuncPermissionDeniedException();
//        }
//        if(permissionEntity.getDataPermissionEntities()==null)
//            return list;
//
//        for (DataPermissionEntity item:permissionEntity.getDataPermissionEntities())
//        {
//            if(item.getDataPermissionQueryFilter()==null)
//                continue;
//            AuthorityInfo tempVar = new AuthorityInfo();
//            tempVar.setFieldName(item.getFieldId());
//            tempVar.setSourceFieldName(item.getDataPermissionQueryFilter().getDataAuthResultDefColumnName());
//            tempVar.setAuthoritySql(item.getDataPermissionQueryFilter().getDataAuthResultFilter());
//            list.add(tempVar);
//        }
//        return list;
//    }

    public static java.util.ArrayList<AuthorityInfo> getAuthorityInfos(BEManagerContext beManagerContext) {
        if (!AuthorityUtil.hasAuthority(beManagerContext))
            return new ArrayList<>();
        List<AuthorityInfo> rez = AuthorityUtil.getAuthorityInfos(beManagerContext.getSessionItem());
        return rez instanceof ArrayList ? (ArrayList) rez : new ArrayList<>(rez);
    }

    @Override
    protected final IMgrActionAssembler getMgrAssembler() {
        return getMgrActionAssemblerFactory().getQueryMgrActionAssembler(getBEManagerContext(), filter);
    }

    /**
     * 通过QueryMgrAction对应的组装器，获取自定义过滤条件
     *
     * @return 自定义过滤条件
     */
    private EntityFilter getCustomEntityFilter() {
        QueryMgrActionAssembler assembler =
                getMgrActionAssemblerFactory().getQueryMgrActionAssembler(getBEManagerContext(), filter);
        return assembler.getNewEntityFilter();
    }

    /**
     * 合并当前过滤条件及装配器中传入的自定义过滤条件 （此处仅考虑过滤和排序的修改，无修改分页的需求）
     *
     * @param currentEntityFilter 构造函数中的过滤条件
     * @param customEntityFilter  组装器中传入的自定义过滤条件
     * @return
     */
    private EntityFilter mergeEntityFilter(
            EntityFilter currentEntityFilter, EntityFilter customEntityFilter) {
        if (customEntityFilter == null) {
            return currentEntityFilter;
        }

        EntityFilter entityFilter = currentEntityFilter;
        if (customEntityFilter.getFilterConditions() != null) {
            entityFilter.addFilterConditions(customEntityFilter.getFilterConditions());
        }
        if (customEntityFilter.getSortConditions() != null) {
            entityFilter.addSortConditions(customEntityFilter.getSortConditions());
        }
        return entityFilter;
    }
}
